#ifndef __WIZ_BNF_SKIPPER_HPP__SHANHAOBO_19800429__
#define __WIZ_BNF_SKIPPER_HPP__SHANHAOBO_19800429__

#include "../WizBNFInfo.hpp"

#include "../WizBNFPolicies.hpp"
#include "./WizBNFParserCharSpace.hpp"

namespace Wiz
{
    namespace BNF
    {
        namespace Skipper
        {
            template <typename SkipT>
            struct Phrase
            {
                template <typename IteratorT, typename ParserT>
                static ::Wiz::BNF::Info::Type<IteratorT>
                Parse
                (
                    IteratorT const&    Frst,
                    IteratorT const&    Lst,
                    ParserT const&      Prsr,
                    SkipT const&        Skp
                )
                {
                    typedef ::Wiz::BNF::Policy::Skipper::Iteration::Parser::Type<SkipT> tIterationPolicy;
                    typedef ::Wiz::BNF::Policy::Scanner<tIterationPolicy>               tScannerPolicy;
                    typedef ::Wiz::BNF::Scanner::Type<IteratorT, tScannerPolicy>        tScanner;

                    tIterationPolicy IterPolicy(Skp);
                    tScannerPolicy Policies(IterPolicy);
                    IteratorT Curr = Frst;
                    tScanner Scan(Curr, Lst, Policies);
                    ::Wiz::BNF::Match::Type<::Wiz::Null::Type> Hit = Prsr.Parse(Scan);
                    return ::Wiz::BNF::Info::Type<IteratorT>(Curr, Hit, Hit && (Curr == Lst), Hit.Length());
                }
            };

            template <>
            struct Phrase<::Wiz::BNF::Parser::Char::Space::Type>
            {
                template <typename IteratorT, typename ParserT>
                static ::Wiz::BNF::Info::Type<IteratorT>
                Parse
                (
                    IteratorT const&    Frst,
                    IteratorT const&    Lst,
                    ParserT const&      Prsr,
                    ::Wiz::BNF::Parser::Char::Space::Type const& WIZ_UNUSED(Skp)
                )
                {
                    typedef ::Wiz::BNF::Policy::Skipper::Iteration::Type<>          tIterationPolicy;
                    typedef ::Wiz::BNF::Policy::Scanner<tIterationPolicy>           tScannerPolicy;
                    typedef ::Wiz::BNF::Scanner::Type<IteratorT, tScannerPolicy>    tScanner;

                    IteratorT Curr = Frst;
                    tScanner Scan(Curr, Lst);
                    ::Wiz::BNF::Match::Type<::Wiz::Null::Type> Hit = Prsr.Parse(Scan);
                    return ::Wiz::BNF::Info::Type<IteratorT>(Curr, Hit, Hit && (Curr == Lst), Hit.Length());
                }
            };

            //////////////////////////////////////////////////////////////////////////

            template <typename ST, typename ScannerT, typename BaseT>
            WIZ_INLINE ::Wiz::Void::Type
            Skip
            (
                ST const& St,
                ScannerT const& Scan,
                ::Wiz::BNF::Policy::Skipper::Iteration::Type<BaseT> const&
            )
            {
                typedef ::Wiz::BNF::Policy::Scanner<
                    ::Wiz::BNF::Policy::NoSkipper::Iteration::Type<typename ScannerT::tIterationPolicy>,
                    typename ScannerT::tMatchPolicy,
                    typename ScannerT::tActionPolicy
                > tPolicies;

                ::Wiz::BNF::Scanner::Type<typename ScannerT::tIterator, tPolicies>
                    Scan2(Scan.m_Curr, Scan.m_Last, tPolicies(Scan));

                for (;;)
                {
                    if (St.Parse(Scan2).NotValid())
                    {
                        break;
                    }
                }
            }

            template <typename ST, typename ScannerT, typename BaseT>
            WIZ_INLINE ::Wiz::Void::Type
            Skip
            (
                ST const& St,
                ScannerT const& Scan,
                ::Wiz::BNF::Policy::NoSkipper::Iteration::Type<BaseT> const&
            )
            {
                for (;;)
                {
                    if (St.Parse(Scan).NotValid())
                    {
                        break;
                    }
                }
            }

            template <typename ST, typename ScannerT>
            WIZ_INLINE ::Wiz::Void::Type
            Skip
            (
                ST const& St,
                ScannerT const& Scan,
                ::Wiz::BNF::Policy::Iteration const&
            )
            {
                for (;;)
                {
                    if (St.Parse(Scan).NotValid())
                    {
                        break;
                    }
                }
            }

        } /// end of namespace Skipper
    } /// end of namespace BNF
} /// end of namespace Wiz

#endif /*__WIZ_BNF_SKIPPER_HPP__SHANHAOBO_19800429__*/

